package com.example2016.cjj.mycustomviewdemo.MyView;

import android.content.Context;
import android.support.v4.view.ViewConfigurationCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;

/**
 * Created by CJJ on 2017/3/4.
 */

public class CustomScrollerView extends ViewGroup {

    private static final String TAG = "CustomScrollerView";

    private Scroller mScroller;

    //滑动与点击的临界点值,超过这个值就是滑动，否则就是点击。
    private int mTouchSlop;

    private int leftBorder,rightBorder;//左右边界

    private VelocityTracker mVelocityTracker;//手指滑动速率

    private int SNAP_VELOCITY = 600;//最小的滑动速率

    private int curScreen=0;//当前显示的屏幕,也就是当前显示的第几个图片View

    private float mXDown;   //手指按下时的x值
    private float mXMove;   //手指移动时的x值
    private boolean interceptFlag=false;//拦截事件标识


    public CustomScrollerView(Context context) {
        this(context,null);
    }

    public CustomScrollerView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public CustomScrollerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        //创建Scroller实例
        mScroller = new Scroller(context);

        //获取TouchSlop值
        ViewConfiguration configuration = ViewConfiguration.get(context);
        mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int childCount = getChildCount();
        for(int i=0; i< childCount; i++){
            View childView = getChildAt(i);
            //测量每一个子控件的大小
            measureChild(childView,widthMeasureSpec,heightMeasureSpec);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if(changed){
            int childCount = getChildCount();
            for(int i=0; i< childCount; i++){
                View childView = getChildAt(i);
                //把每一个子控件在水平方向上布局
                childView.layout(i*childView.getMeasuredWidth(),0
                        ,(i+1)*childView.getMeasuredWidth(),childView.getMeasuredHeight());
            }

            // 初始化左右边界值
            leftBorder = getChildAt(0).getLeft();
            rightBorder = getChildAt(getChildCount() - 1).getRight();
        }

    }



    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {

        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                mXDown = ev.getRawX();

                interceptFlag= false;
                break;
            case MotionEvent.ACTION_MOVE:
                mXMove = ev.getRawX();
                float diffX = Math.abs(mXMove - mXDown);
                //当手指拖动值大于TouchSlop时，认为应该是进行滚动，拦截子控件的事件
                if( diffX > mTouchSlop){
                   interceptFlag = true;
                }

                mXDown = mXMove;
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                interceptFlag= false;
                break;
        }

        return interceptFlag;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        if(mVelocityTracker== null){
            mVelocityTracker = VelocityTracker.obtain();    //获取速率追踪器实例
        }
        mVelocityTracker.addMovement(event);


        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                //如果上一次滚动动画还没结束，手指又按下了，那么我们结束上一次动画。
                if(mScroller !=null){
                    if( !mScroller.isFinished() ){
                        mScroller.abortAnimation();
                    }
                }
                mXDown = event.getRawX();
                break;
            case MotionEvent.ACTION_MOVE:
                mXMove = event.getRawX();
                int scrolledX = (int) (mXDown - mXMove);

                if(getScrollX() + scrolledX <leftBorder){
                    scrollTo(leftBorder,0);
                    return true;
                }else if( getScrollX() + getWidth()+ scrolledX > rightBorder){
                    scrollTo(rightBorder-getWidth(),0);
                    return true;
                }

                scrollBy(scrolledX,0);
                mXDown = mXMove;
                break;
            case MotionEvent.ACTION_UP:
                final VelocityTracker velocityTracker = mVelocityTracker;
                //计算速率
                velocityTracker.computeCurrentVelocity(1000);
                //获取x轴的速率值,向左滑是负值，向右滑是正值
                float velocityX =velocityTracker.getXVelocity();

                //判断速率是否超过了定义的最小速率，如果超过了，那就滑到上\下一页，
                // 否则就正常滑动（判断是否过了宽度的一半，如果超过一般,那就滑到上\下一页）
                if( Math.abs( velocityX ) > SNAP_VELOCITY){
                    if( velocityX <0){
                        //左滑
                        SnapToScreen(curScreen +1);
                    }else  if( velocityX > 0){
                        //右滑
                        SnapToScreen(curScreen -1);
                    }

                }else {
                    WidthToScreen();
                }
                break;
        }


        return true;
    }

    //根据宽度，切换到下一屏幕
    private void WidthToScreen() {

        // 当手指抬起时，根据当前的滚动值来判定应该滚动到哪个子控件的界面
        int targetIndex = (getScrollX() + getWidth() / 2) / getWidth();
        SnapToScreen(targetIndex);

    }

    //根据速率，切换到下一屏幕
    private void SnapToScreen(int whichScreen) {
        curScreen = whichScreen;
        //防止越界
        if( curScreen <0){
            curScreen = 0;
        }else if(curScreen > getChildCount()-1){
            curScreen = getChildCount()-1;
        }

        int dx = curScreen * getWidth() - getScrollX();
        // 调用startScroll()方法来初始化滚动数据并刷新界面
        mScroller.startScroll(getScrollX(), 0, dx, 0);
        invalidate();
    }


    @Override
    public void computeScroll() {
        // 重写computeScroll()方法，并在其内部完成平滑滚动的逻辑
        if( mScroller.computeScrollOffset()){
            scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
            invalidate();
        }
    }
}
